#pragma once

#include "singlelayeractor.h"
#include <osg\ref_ptr>
#include "fogsettingactor.h"
#include "skydomeactor.h"
#include "oceanactor.h"
#include "terrainbrushactor.h"
#include <osgUtil\CullVisitor>
#include "overallsoundactor.h"
#include "datacoredefine.h"
#include "weathersetting.h"

namespace VrDataCore
{
	class Map;
	class CameraTrackCallback;

	class VRDATACORE_EXPORT EnvironmentLayerActor:public SingleLayerActor
	{
	public:
		struct EnvironmentData
		{
			QVector<QString>		_cubemapDirs;
			QVector<osg::Vec4f>		_lightColors;
			QVector<osg::Vec4f>		_fogColors;
			QVector<osg::Vec3f>		_underwaterAttenuations;
			QVector<osg::Vec4f>		_underwaterDiffuse;
			QVector<osg::Vec4f>		_sunDiffuse;
			QVector<osg::Vec4f>		_waterFogColors;
			bool					_enableOcean;
			bool					_enableSkyDome;
		};
		enum EnvironmentType
		{
			CLEAR,
			CLOUDY,
			DUSK,
			NIGHT,
		};
		struct FogSetting
		{
			bool									_open;
			osg::Vec4								_fogColor;
			float									_density;
			float									_start;
			float									_end;
		};
		struct OceanSetting
		{
			bool					_enable;
			osg::Vec2				_size;
			QString					_rotate;
			osg::Vec3				_pos;
			QString					_active;
			int						_oceanType;
			int						_foamHeight;
			int						_waveScale;
			osg::Vec3				_sunPosition;
		};
		EnvironmentLayerActor();
		virtual void addEnvironmentChild(QVector<QString> meshnames,QVector<osg::Vec3> posvec,int collisiontype = 0);
		virtual void removeEnvironmentChild(QVector<osg::Vec3> posvec);
		virtual QVector<osg::Vec3> getEnvironmentObjects(const osg::Vec3& center,float radious);
		virtual QVector<osg::Vec3> getEnvironmentObjects(const osg::Vec3& min,const osg::Vec3& max);
		virtual void addChild(CoreBase::ActorBase* mactor);
		virtual void removeChild(CoreBase::ActorBase* mactor);
		EnvironmentType getCurrentSkyType();
		void setSkyDomeEnable(bool enable,QString type,const QString& active,float radius);
		void getSkyDomeEnable(bool& enable,QString& type,QString& active,float& radius);
		void setOceanEnable(OceanSetting setting);
		void getOceanEnable(OceanSetting& setting,bool& valid);
		CoreBase::ActorBase* getFogSettingActor();
		void mapChangeClear();
		osg::ref_ptr<TransformableActor> getOrCreateTerrainBrush();
		virtual void buildPropertyMap();
		virtual void onMapLoadEnd(CoreBase::Map*);
		void useFogSetting();
		void getOceanSurfaceHeight(osg::Vec3& pos);
		void updateByEye(const osg::Vec3& eye);
		osg::Vec3 getSkyOffset() const;
		osg::Vec3 getOceanOffset() const;
		void setNight(bool n);
		bool isNight();
		CoreBase::ActorBase* getOverallSoundEffectActor();
		void setOverallSoundEnable(bool e);
		
		CoreBase::ActorBase* getWeatherSetting();
		void setWeatherSetting(CoreBase::ActorBase* s);
		void setSunTranslation(osg::Vec3 pos);
		osg::Vec3 getSunTranslation();
	protected:
		~EnvironmentLayerActor();
		void initEnvironmentData();
		void changeWithSky();
		osg::Vec4f intColor(unsigned int r, unsigned int g, unsigned int b, unsigned int a = 255 );
		void createFogActor(CoreBase::Map* currmap);
		virtual void createDrawable();
		QMap<QString,CoreBase::ActorBase*>										_nameToNode;
		EnvironmentData															_environmentData;
		EnvironmentType															_currentSkyType;
		QVector<FogSetting>														_defaultFogSettingVector;
		osg::ref_ptr<SkyDomeActor>												_skyDomeActor;
		osg::ref_ptr<WeatherSetting>											_weatherSetting;
		osg::ref_ptr<OceanActor>												_oceanActor;
		osg::ref_ptr<TerrainBrushActor>											_terrainBrushActor;
		osg::ref_ptr<FogSettingActor>											_fogActor;
		osg::ref_ptr<CameraTrackCallback>										_cameraTrackCallback;
		OverallSoundActor*														_overallSoundActor;
		bool																	_isNight;
		osg::Vec3																_sunPosition;
	};

	class CameraTrackCallback: public osg::NodeCallback
	{
	public:
		CameraTrackCallback(EnvironmentLayerActor* layer)
		{
			_layer = layer;
		}
		virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
		{
			if(nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
			{
				osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
				if(cv->getRenderStage()->getCamera()->getName() != SLAVEVIEW_EFFECT_CAMERA)
				{
					osg::Vec3f centre,up,eye;
					// get MAIN camera eye,centre,up
					cv->getRenderStage()->getCamera()->getViewMatrixAsLookAt(eye,centre,up);
					// update position
					//osg::MatrixTransform* mt = static_cast<osg::MatrixTransform*>(node);
					//mt->setMatrix( osg::Matrix::translate( eye.x(), eye.y(), mt->getMatrix().getTrans().z() ) );
					_layer->updateByEye(eye);
				}
			}
			traverse(node, nv); 
		}
		~CameraTrackCallback(){}
		private:
			EnvironmentLayerActor*								_layer;
	};
}